#include "stdafx.h"
#include "..\headers\LuaSystem.h"
#include "..\headers\InputSystem.h"
#include "..\headers\LuaEngine.h"
#include "..\headers\GameTime.h"
#include "..\headers\PhysicsWorld.h"
#include "..\headers\StateManager.h"
#include "..\headers\GameObjectManager.h"
#include "..\headers\PhysicsPrereq.h"
#include "..\headers\VisualComponents.h"
namespace ne{
class LuaGameObject;
static InputSystem* g_inputSystem = nullptr;
namespace Input {
	static bool MouseButtonDown(int btn){return g_inputSystem->IsMouseButtonDown(btn);}
	static bool MouseButtonPressed(int btn){return g_inputSystem->IsMouseButtonPressed(btn);}
	static bool MouseButtonReleased(int btn){return g_inputSystem->IsMouseButtonReleased(btn);}
	static bool KeyDown(int key){return g_inputSystem->IsKeyDown(key);}
	static bool KeyPressed(int key){return g_inputSystem->IsKeyPressed(key);}
	static bool KeyReleased(int key){return g_inputSystem->IsKeyReleased(key);}
	static OIS::MouseState Mouse(){return g_inputSystem->GetMouseState();}
	static bool ButtonDown(const char* btn){return g_inputSystem->IsButtonDown(btn);}
	static bool ButtonDown(const char* btn, int joystickID){return g_inputSystem->IsButtonDown(btn,joystickID);}
	static bool ButtonPressed(const char* btn){return g_inputSystem->IsButtonPressed(btn);}
	static bool ButtonPressed(const char* btn, int joystickID){return g_inputSystem->IsButtonPressed(btn,joystickID);}
	static bool ButtonReleased(const char* btn){return g_inputSystem->IsButtonReleased(btn);}
	static bool ButtonReleased(const char* btn, int joystickID){return g_inputSystem->IsButtonReleased(btn,joystickID);}
	static bool JoystickDown(int btn, int joystickID){return g_inputSystem->IsJoyStickButtonDown(btn,joystickID);}
	static bool JoystickDown(int btn){return g_inputSystem->IsJoyStickButtonDown(btn,0);}
	static bool JoystickPressed(int btn, int joystickID){return g_inputSystem->IsJoyStickButtonPressed(btn,joystickID);}
	static bool JoystickPressed(int btn){return g_inputSystem->IsJoyStickButtonPressed(btn,0);}
	static bool JoystickReleased(int btn, int joystickID){return g_inputSystem->IsJoyStickButtonReleased(btn,joystickID);}
	static bool JoystickReleased(int btn){return g_inputSystem->IsJoyStickButtonReleased(btn,0);}
	static float GetJoystickAxis(int axis, int joystickID){return g_inputSystem->GetJoystickAxis(axis,joystickID);}
	static float GetJoystickAxis(int axis){return g_inputSystem->GetJoystickAxis(axis,0);}
	static int GetJoystickPov(int joystickID){return g_inputSystem->GetJoystickPov(joystickID);}
	static int GetJoystickPov(void){return g_inputSystem->GetJoystickPov(0);}
	static bool JoystickPovDown(int pov,int joystickID){return g_inputSystem->IsJoyStickPovDown(pov,joystickID);}
	static bool JoystickPovDown(int pov){return g_inputSystem->IsJoyStickPovDown(pov,0);}
	static bool JoystickPovPressed(int pov,int joystickID){return g_inputSystem->IsJoyStickPovPressed(pov,joystickID);}
	static bool JoystickPovPressed(int pov){return g_inputSystem->IsJoyStickPovPressed(pov,0);}
	static bool JoystickPovReleased(int pov,int joystickID){return g_inputSystem->IsJoyStickPovReleased(pov,joystickID);}
	static bool JoystickPovReleased(int pov){return g_inputSystem->IsJoyStickPovReleased(pov,0);}

	void Init(LuaEngine* luaEngine, InputSystem* inputSystem){
		g_inputSystem = inputSystem;
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("MouseButtonDown",MouseButtonDown)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("MouseButtonPressed",MouseButtonPressed)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("MouseButtonReleased",MouseButtonReleased)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("KeyDown",KeyDown)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("KeyPressed",KeyPressed)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("KeyReleased",KeyReleased)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("Mouse",Mouse)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("ButtonDown",(bool(*)(const char*))ButtonDown)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("ButtonDown",(bool(*)(const char*,int))ButtonDown)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("ButtonPressed",(bool(*)(const char*))ButtonPressed)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("ButtonPressed",(bool(*)(const char*,int))ButtonPressed)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("ButtonReleased",(bool(*)(const char*))ButtonReleased)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("ButtonReleased",(bool(*)(const char*,int))ButtonReleased)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickDown",(bool(*)(int))JoystickDown)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickDown",(bool(*)(int,int))JoystickDown)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPressed",(bool(*)(int))JoystickPressed)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPressed",(bool(*)(int,int))JoystickPressed)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickReleased",(bool(*)(int))JoystickReleased)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickReleased",(bool(*)(int,int))JoystickReleased)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickAxis",(float(*)(int))GetJoystickAxis)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickAxis",(float(*)(int,int))GetJoystickAxis)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPov",(int(*)(int))GetJoystickPov)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPov",(int(*)(void))GetJoystickPov)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPovDown",(bool(*)(int))JoystickPovDown)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPovDown",(bool(*)(int,int))JoystickPovDown)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPovPressed",(bool(*)(int))JoystickPovPressed)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPovPressed",(bool(*)(int,int))JoystickPovPressed)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPovReleased",(bool(*)(int))JoystickPovReleased)];
		luabind::module(luaEngine->GetState(),"Input")[luabind::def("JoystickPovReleased",(bool(*)(int,int))JoystickPovReleased)];
	}
}	// namespace Input

namespace Time {
	static GameTime* g_gameTime = nullptr;

	static float DeltaTime(){return g_gameTime->DeltaTime();}
	static float TotalTime(){return g_gameTime->Time();}

	void Init(LuaEngine* luaEngine, GameTime* gameTime){
		g_gameTime = gameTime;
		luabind::module(luaEngine->GetState(),"Time")[luabind::def("DeltaTime",DeltaTime)];
		luabind::module(luaEngine->GetState(),"Time")[luabind::def("TotalTime",TotalTime)];
	}
} // namespace Time

// Yomi Specific systems - begin
static void RemoveWeights(std::vector<std::string>& list,Ogre::Entity* p_entity,Ogre::Animation* p_anim){
	Ogre::Skeleton::BoneIterator bone_it = p_entity->getSkeleton()->getBoneIterator();
	while (bone_it.hasMoreElements()){
		Ogre::Bone* bone = bone_it.getNext();
		Ogre::String bone_id = bone->getName();
		std::vector<std::string>::iterator it = std::find(list.begin(), list.end(), bone_id);
		if (it != list.end()){
			p_anim->destroyNodeTrack(bone->getHandle());
		}
	}
}

static void FixYomiWeights(MeshComponent* meshComp){
	Ogre::Entity* ent=meshComp->GetEntity();
	std::vector<std::string> base_anims;
	base_anims.push_back("CATRigLLegPlatform");
	base_anims.push_back("CATRigLLegAnkle");
	base_anims.push_back("CATRigLLeg2");
	base_anims.push_back("CATRigLLeg1");
	base_anims.push_back("Yomi_Pelvis");
	base_anims.push_back("CATRigRLeg1");
	base_anims.push_back("CATRigRLeg2");
	base_anims.push_back("CATRigRLegAnkle");
	base_anims.push_back("CATRigAnkleBone001");
	base_anims.push_back("CATRigRLegPlatform");
	base_anims.push_back("CATRigTail1");
	base_anims.push_back("CATRigTail2");
	base_anims.push_back("CATRigTail3");
	base_anims.push_back("CATRigTail4");
	base_anims.push_back("CATRigTail5");
	std::vector<std::string> top_anims;
	top_anims.push_back("CATRigSpine1");
	top_anims.push_back("CATRigSpine2");
	top_anims.push_back("CATRigSpine3");
	top_anims.push_back("Yomi_Torso");
	top_anims.push_back("CATRigLArmCollarbone");
	top_anims.push_back("CATRigLArm1");
	top_anims.push_back("CATRigLArm21");
	top_anims.push_back("CATRigLArm22");
	top_anims.push_back("CATRigLArmPalm");
	top_anims.push_back("CATRigLArmDigit21");
	top_anims.push_back("CATRigLArmDigit22");
	top_anims.push_back("CATRigLArmDigit11");
	top_anims.push_back("CATRigRArmCollarbone");
	top_anims.push_back("CATRigRArm1");
	top_anims.push_back("CATRigRArm21");
	top_anims.push_back("CATRigRArm22");
	top_anims.push_back("CATRigRArmPalm");
	top_anims.push_back("CATRigRArmDigit21");
	top_anims.push_back("CATRigRArmDigit22");
	top_anims.push_back("CATRigRArmDigit11");
	top_anims.push_back("CATRigRightHair1");
	top_anims.push_back("CATRigRightHair2");
	top_anims.push_back("CATRigRightHair3");
	top_anims.push_back("CATRigLeftHair1");
	top_anims.push_back("CATRigLeftHair2");
	top_anims.push_back("CATRigLeftHair3");
	top_anims.push_back("CATRigBackHair1");
	top_anims.push_back("CATRigBackHair2");
	top_anims.push_back("CATRigBackHair3");
	top_anims.push_back("Yomi_Head");

	Ogre::String line = Ogre::StringUtil::BLANK;
	Ogre::String anim_id = Ogre::StringUtil::BLANK;
	Ogre::String base = "Base";
	Ogre::String top = "Top";

	for (int i = 0; i < ent->getSkeleton()->getNumAnimations(); i++){
		Ogre::Animation* anim = ent->getSkeleton()->getAnimation(i);
		anim_id = anim->getName();
		size_t find = anim_id.find(base);
		if (find  != std::string::npos){
			RemoveWeights(top_anims,ent,anim);
			continue;
		}
		find = anim_id.find(top);
		if (find != std::string::npos){
			RemoveWeights(base_anims,ent,anim);
			continue;
		}
	}
}
// Yomi Specific Systems - end

namespace LuaSystem{
	static Ogre::SceneManager* g_sceneManager=nullptr;
	static GameObjectManager* g_gameObjectManager=nullptr;
	static PhysicsWorld* g_physicsWorld=nullptr;
	static StateListener* g_stateListener=nullptr;
	static void Print(const Ogre::Vector4& vec4){std::cout<<vec4<<"\n";}
	static void Print(const Ogre::Vector3& vec3){std::cout<<vec3<<"\n";}
	static void Print(const Ogre::Vector2& vec2){std::cout<<vec2<<"\n";}
	static void Print(const Ogre::Quaternion& quat){std::cout<<quat<<"\n";}
	static void ChangeState(const char* stateName){g_stateListener->ChangeState(g_stateListener->FindByName(stateName));}
	static void SetSkyBox(const char* material, float distance){g_sceneManager->setSkyBox(true,material,distance);}
	static void SetSkyDome(const char* material,float curvature,float tiling,float distance){g_sceneManager->setSkyDome(true,material,curvature,tiling,distance);}
	static void DisableSkyDome() {g_sceneManager->setSkyDomeEnabled(false);}
	static void DisableSkyBox() {g_sceneManager->setSkyBoxEnabled(false);}
	static void RayTest(const Ogre::Vector3& from,const Ogre::Vector3& to,IgnoreObjectCast& ignoreBodyCast){
		g_physicsWorld->GetDynamicWorld()->rayTest(Convert::ToBullet(from),Convert::ToBullet(to),ignoreBodyCast);
	}
	static bool CreateObject(LuaGameObject* luaObject){return g_gameObjectManager->AddGameObject(luaObject);}
	static bool RemoveObject(LuaGameObject* luaObject){return g_gameObjectManager->RemoveGameObject(luaObject);}
	void Init(LuaEngine* luaEngine,PhysicsWorld* physicsWorld,StateListener* stateListener){
		g_physicsWorld = physicsWorld;
		g_stateListener = stateListener;
		luabind::module(luaEngine->GetState(),"System")[luabind::def("Print",(void(*)(const Ogre::Vector4&))Print)];
		luabind::module(luaEngine->GetState(),"System")[luabind::def("Print",(void(*)(const Ogre::Vector3&))Print)];
		luabind::module(luaEngine->GetState(),"System")[luabind::def("Print",(void(*)(const Ogre::Vector2&))Print)];
		luabind::module(luaEngine->GetState(),"System")[luabind::def("Print",(void(*)(const Ogre::Quaternion&))Print)];
		luabind::module(luaEngine->GetState(),"State")[luabind::def("SetSkyBox",SetSkyBox)];
		luabind::module(luaEngine->GetState(),"State")[luabind::def("DisableSkyBox",DisableSkyBox)];
		luabind::module(luaEngine->GetState(),"State")[luabind::def("SetSkyDome",SetSkyDome)];
		luabind::module(luaEngine->GetState(),"State")[luabind::def("DisableSkyDome",DisableSkyDome)];
		luabind::module(luaEngine->GetState(),"State")[luabind::def("ChangeState",ChangeState)];
		luabind::module(luaEngine->GetState(),"State")[luabind::def("CreateObject",CreateObject)];
		luabind::module(luaEngine->GetState(),"State")[luabind::def("RemoveObject",RemoveObject)];
		luabind::module(luaEngine->GetState(),"Physics")[luabind::def("RayTest",RayTest)];
		luabind::module(luaEngine->GetState(),"YomiAnim")[luabind::def("FixWeights",FixYomiWeights)];
	}
	void InitState(Ogre::SceneManager* sceneManager,GameObjectManager* gameObjectManager){g_sceneManager=sceneManager;g_gameObjectManager=gameObjectManager;}
}	// namespace LuaSystem

} // namespace ne

